package cn.wolfcode.crm.service.imp;

import cn.wolfcode.crm.domain.*;
import cn.wolfcode.crm.mapper.AccountBookMapper;
import cn.wolfcode.crm.mapper.OrderBillItemMapper;
import cn.wolfcode.crm.mapper.OrderBillMapper;
import cn.wolfcode.crm.mapper.StockMapper;
import cn.wolfcode.crm.qo.PageResult;
import cn.wolfcode.crm.qo.QueryObject;
import cn.wolfcode.crm.service.IOrderBillService;
import cn.wolfcode.crm.util.UUIDUtil;
import cn.wolfcode.crm.util.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
public class OrderBillServiceImpl implements IOrderBillService {
    @Autowired
    private OrderBillMapper orderBillMapper;
    @Autowired
    private OrderBillItemMapper orderBillItemMapper;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private AccountBookMapper accountBookMapper;
    @Override
    public void saveOrUpdate(OrderBill entity) {
        if (entity.getItems().size() == 0) {
            throw new RuntimeException("至少要有1条商品明细");
        }
        if (!Optional.ofNullable(entity.getId()).isPresent()) {
            saveBill(entity);
        }else {
            updateBill(entity);
        }
    }
    //更新单据的业务操作
    private void updateBill(OrderBill entity) {
        //判断当前单据是否是未审核状态的
        OrderBill old = orderBillMapper.selectByPrimaryKey(entity.getId());
        if (old.getStatus() == OrderBill.NO_AUDITED) {
            //删除旧的明细
            orderBillMapper.deleteItemsByBillId(entity.getId());
            //重新计算新的小计和总计
            BigDecimal totalNumber = BigDecimal.ZERO;
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (OrderBillItem item : entity.getItems()) {
                //重新计算小计
                BigDecimal amount = item.getCostPrice()
                        .multiply(item.getNumber().setScale(2,RoundingMode.HALF_UP));
                item.setAmount(amount);
                //累加到总计上
                totalNumber = totalNumber.add(item.getNumber());
                totalAmount = totalAmount.add(amount);
                //已知单据id,可直接保存明细
                item.setBillId(entity.getId());
                orderBillItemMapper.insert(item);
            }
            old.setTotalNumber(totalNumber);
            old.setTotalAmount(totalAmount);
            //新的信息同步过来
            old.setSn(entity.getSn());
            old.setVdate(entity.getVdate());
            old.setSupplier(entity.getSupplier());
            old.setDepot(entity.getDepot());
            old.setProductSortTwo(entity.getProductSortTwo());
            //更新单据
            orderBillMapper.updateByPrimaryKey(old);
        }
    }
    //新增单据的业务操作
    private void saveBill(OrderBill entity) {
        //1.所有的关键信息必须手动设置一遍
        //单据状态 录入人 录入时间
        entity.setStatus(OrderBill.NO_AUDITED);//设置默认未审核
        entity.setInputTime(new Date());//设置录入时间
        entity.setInputUser(UserContext.getCurrentUser());//本系统默认设置录入人为登陆人
        entity.setSn(UUIDUtil.getUUID());
        //2.重新后台计算明细的小计和单据的总计
        BigDecimal totalNumber = BigDecimal.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (OrderBillItem item : entity.getItems()) {
            //重新计算小计
            BigDecimal amount = item.getCostPrice()
                    .multiply(item.getNumber().setScale(2,RoundingMode.HALF_UP));
            item.setAmount(amount);
            //累加到总计上
            totalNumber = totalNumber.add(item.getNumber());
            totalAmount = totalAmount.add(amount);
        }
        entity.setTotalAmount(totalAmount);
        entity.setTotalNumber(totalNumber);
        //保存到数据库
        orderBillMapper.insert(entity);
        //单据有多个,需遍历;且新增时,由于还没有单据id,需等单据保存完毕后,再保存明细
        for (OrderBillItem item : entity.getItems()) {
            //每个明细设置对应的单据ID
            item.setBillId(entity.getId());
            orderBillItemMapper.insert(item);
        }
    }

    @Override
    public void delete(Long id) {
        OrderBill old = orderBillMapper.selectByPrimaryKey(id);
        //判断当前单据必须是未审核状态
        if (old.getStatus() == OrderBill.NO_AUDITED) {
            //先删除明细再删除单据
            orderBillMapper.deleteItemsByBillId(id);
            orderBillMapper.deleteByPrimaryKey(id);
        }
    }

    @Override
    public OrderBill get(Long id) {
        return orderBillMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageResult query(QueryObject qo) {
        Integer rows = orderBillMapper.selectForCount(qo);
        if (rows == 0) {
            return PageResult.EMPTY_RESULT;
        }
        List<?> data = orderBillMapper.selectForList(qo);
        PageResult result = new PageResult(rows,data);
        return result;
    }

    @Override
    public void audit(Long id) {
        //先检查当前单据的状态,必须是未审核状态
        OrderBill bill = orderBillMapper.selectByPrimaryKey(id);
        if (bill.getStatus() == OrderBill.NO_AUDITED) {
            bill.setStatus(OrderBill.AUDITED);
            bill.setAuditor(UserContext.getCurrentUser());
            bill.setAuditTime(new Date());
            for(OrderBillItem item : bill.getItems()) {
                //拿到当前明细中进入的商品
                Product p = item.getProduct();
                //查询当前库存中是否有该商品
                Stock stock = stockMapper.selectByProductId(p.getId());
                //如果已经有库存
                if (Optional.ofNullable(stock).isPresent()) {
                    //再算数量
                    BigDecimal number = stock.getNumber().add(item.getNumber());
                    //设置到数据库
                    stock.setNumber(number);
                    stock.setSn(p.getProductSn());
                    stock.setProductId(p.getId());
                    stock.setProductname(p.getProductName());
                    stockMapper.updateByPrimaryKey(stock);
                }else {
                    //库存中还没有这个商品,可以直接存入
                    stock = new Stock();
                    stock.setNumber(item.getNumber());
                    stock.setSn(p.getProductSn());
                    stock.setProductId(p.getId());
                    stock.setProductname(p.getProductName());
                    stockMapper.insert(stock);
                }
            }
            //完成审核更新操作
            orderBillMapper.audit(bill);
            AccountBook book = new AccountBook();
            //出总账
            book.setBillId(bill.getId());
            book.setInputTime(new Date());
            book.setSn(false);
            book.setAmount(bill.getTotalAmount());
            accountBookMapper.insert(book);
        }
    }

    @Override
    public List<OrderBill> selectBySn(String sn) {
        return orderBillMapper.selectBySn(sn);
    }
}
